package pt.c01interfaces.s01chaveid.debolacha;

import java.util.Enumeration;
import java.util.Hashtable;

import pt.c01interfaces.s01chaveid.s01base.impl.*;
import pt.c01interfaces.s01chaveid.s01base.inter.*;

public class EnquirerAdvanced implements IEnquirer{

	private String[] lista;
	private Hashtable<Integer, String> animal;
	private Hashtable<Integer, Pergunta> pergunta;
	
	/*Constroi um hash de perguntas e um hash de animais*/
	public EnquirerAdvanced(){
    	/*Carrega a base de dados*/
		BaseConhecimento base = new BaseConhecimento();
        lista = base.listaNomes();
        
        /*Variaveis usadas na construcao dos hashes*/
        IObjetoConhecimento obj;
        IDeclaracao decl;
        Pergunta prop;
        
        
        /*Cria os hashes*/
        int tam = lista.length;
        animal = new Hashtable<Integer, String>((int)1.2*tam);
        pergunta = new Hashtable<Integer, Pergunta>(5*tam);
        
        /*Carrega os hashes com os objetos de conhecimento*/
        for(int i = 0; i < tam; i++){
        	/*Adiciona um animal ao hash de animais*/
        	animal.put(index(lista[i]), lista[i]);
        	obj = base.recuperaObjeto(lista[i]);
        	
        	/*Adiciona as propriedades do animal ao hash de perguntas*/
        	decl = obj.primeira();
        	while(decl != null){
        		/*Cria um objeto Pergunta generico*/
        		prop = new Pergunta(decl.getPropriedade());

        		/*Caso a propriedade ainda exista no hash pergunta,
        		 *a lista apropriada recebe um ponteiro para o animal*/
    			if(pergunta.containsValue(prop))
    				pergunta.get(index(decl.getPropriedade())).adiciona_animal(decl.getValor(), animal.get(index(lista[i])));
    			/*Se a propriedade nao existir, eh instanciado um objeto Pergunta*/
    			else
    				pergunta.put(index(decl.getPropriedade()), new Pergunta(decl, animal.get(index(lista[i]))));
    			
    			/*Vai para a proxima propriedade*/
    			decl = obj.proxima();
    		}
        }

        /*Caso um animal nao possua uma pergunta, ele sera
         *apontado pela pergunta atraves do arraylist nao_sei*/
    
	}
	
	/*Retorna a chave de uma string para seu hash*/
	public static Integer index(String str){
		int i,
			soma = 0;
		
		/*Faz uma conta para atribuir um inteiro a uma String*/
		for(i=0; i< str.length(); i++){
			if(i%4 == 0)
				soma += str.charAt(i);
			if(i%4 == 1)
				soma *= str.charAt(i);
			if(i%4 == 2)
				soma -= str.charAt(i);
			if(i%4 == 3)
				soma /= (float)str.charAt(i);
		}
		
		/*A funcao utiliza um produto para escolher o indice*/
		return new Integer(soma);
	}
	
	public void connect(IResponder responder){
		Lista solucao;
		boolean acertei = false;
		
		/*Carrega um animal da base de conhecimento*/
		IBaseConhecimento bc = new BaseConhecimento();
		IObjetoConhecimento obj = bc.recuperaObjeto("tiranossauro");
		
		/*Cria uma lista com os animais que nao eliminaram a primeira propriedade*/
		IDeclaracao decl = obj.primeira();
		solucao = pergunta.get(index(decl.getPropriedade())).getLista(decl.getValor()).uniao(pergunta.get(index(decl.getPropriedade())).getLista("nao sei"));
		
		/*A cada propriedade do animal, a sloucao torna-se a interseccao
		 *de si com a lista dos animais que nao eliminam tal propriedade*/
		while(decl != null){
			solucao = solucao.intersec(pergunta.get(index(decl.getPropriedade())).getLista(decl.getValor()).uniao(pergunta.get(index(decl.getPropriedade())).getLista("nao sei")));
			decl = obj.proxima();
		}
		
		/*Caso a base de dados seja correta, havera um unico animal que satifaz todas as propriedades*/
		if(solucao.size() == 1){
			acertei = responder.finalAnswer(solucao.get(0));
		}
		
		/*Se alguma pergunta for respondida erroneamente,
		 *pode ser que o animal nao exista na base de dados*/
		else if(solucao.isEmpty())
			acertei = responder.finalAnswer("nenhum");
		
		/*Se a base de dados possuir animais que nao eliminem nenhuma propriedade
		 *de algum outro animal, qualquer um pode ser o animal desejado*/
		else
			for(int i=0; i<solucao.size(); i++){
				acertei = responder.finalAnswer(solucao.get(i));
				if(acertei) break;
			}
			/*NOTA: AQUI, O PROGRAMA DESRESPEITA A REGRA DE CHAMAR O METODO FINALaNSWER()SOMENTE UMA VEZ.
			 *POREM, ESTE LACO SOH EH EXECUTADO SE A BASE DE DADOS FOR INCONSISTENTE*/

		if(acertei)
			System.out.println("Oba! Acertei!");
		else
			System.out.println("Fuem!Fuem!Fuem!");
		return /*acertei*/;
	}

	public static void main(String[] args){
		EnquirerAdvanced var = new EnquirerAdvanced();
		
		for(Enumeration<Integer> e = var.getA().keys(); e.hasMoreElements(); )
			System.out.println(var.getA().get(e.nextElement()));
			/*IMPRIMIR AS PERGUNTAS TBM*/
	}
	
	public Hashtable<Integer, String> getA(){
		return this.animal;
	}
}
